#include "userdefine.h"
#include "datamanagement/mainwindows/mainwindow.h"

// -----------------------------------------自定义常量和静态变量，数据库表和界面表格显示相关------------------------------------------------------------------------------

//===========主界面对象静态变量============================================
// 主界面对象相关
QMainWindow* UserDefineConstant::MAIN_WINDOW = NULL;


//===========自定义字段表相关常量==========================================
// 数据库自定义字段表的字段信息
const QString UserDefineConstant::COLUMN_TABLE_NAME = "column_table"; // 数据库自定义字段表的表名
const QString UserDefineConstant::TABLE_CONNECT_TABLE = "connect_table";
const QString UserDefineConstant::TABLE_COLUMN_NAME = "column_name";
const QString UserDefineConstant::TABLE_COLUMN_ZN_NAME = "column_zn_name";
const QString UserDefineConstant::TABLE_COLUMN_IS_UNIQUE = "column_is_unique";
const QString UserDefineConstant::TABLE_COLUMN_IS_REQUIRED = "column_is_required";

// 自定义字段表在界面对应的表格显示的每列的中文名称
const QString UserDefineConstant::TABLE_CONNECT_TABLE_ZN_TITLE = "关联表";
const QString UserDefineConstant::TABLE_COLUMN_NAME_ZN_TITLE = "字段名称";
const QString UserDefineConstant::TABLE_COLUMN_ZN_NAME_ZN_TITLE = "字段中文名称";
const QString UserDefineConstant::TABLE_COLUMN_IS_UNIQUE_ZN_TITLE = "是否唯一";
const QString UserDefineConstant::TABLE_COLUMN_IS_REQUIRED_ZN_TITLE = "是否必填";


//===========自定义表相关常量============================================
// 数据库自定义表的字段信息
const QString UserDefineConstant::USERDEFINE_TABLE_TABLE_NAME= "userdefine_table"; // 数据库自定义表的表名
const QString UserDefineConstant::USERDEFINE_TABLE_COLUMN_TABLE_NAME = "table_name";
const QString UserDefineConstant::USERDEFINE_TABLE_COLUMN_TABLE_ZN_NAME = "table_zn_name";

// 自定义表在界面对应的表格显示的每列的中文名称
const QString UserDefineConstant::USERDEFINE_TABLE_COLUMN_TABLE_NAME_ZN_TITLE = "表名";
const QString UserDefineConstant::USERDEFINE_TABLE_COLUMN_TABLE_ZN_NAME_ZN_TITLE = "表中文名";


//===========通用性常量=================================================
// 界面表格显示的主键的中文名称
const QString UserDefineConstant::ID_ZN_NAME = "主键(id)";
// 数据库中所有表的id字段名称
const QString UserDefineConstant::ID_COLUMN_NUIQUE_NAME = "id";
// 界面表格的复选框列显示的中文名称
const QString UserDefineConstant::CHECK_BOX_CN_NAME = "*选择栏";
// bool值true的中文表示
const QString UserDefineConstant::BOOL_ZN_NAME_TRUE = "是";
// bool值false的中文表示
const QString UserDefineConstant::BOOL_ZN_NAME_FALSE = "否";


//===========内置表数据（学生表）常量=====================================
// 数据库学生表的表名
const QString UserDefineConstant::STUDENT_TABLE_NAME = "student_table";
// 界面列表显示的学生表对应的中文名称
const QString UserDefineConstant::STUDENT_TABLE_ZN_NAME = "学生信息";


//===========配置setting文件相关常量和静态变量====================================
// 数据库相关
const QString UserDefineConstant::SQL_DRIVE_SQLLITE_NAME = "sqllite";
const QString UserDefineConstant::SQL_DRIVE_MYSQL_NAME = "mysql";
QString UserDefineConstant::DATA_BASE_DRIVE_NAME = UserDefineConstant::SQL_DRIVE_SQLLITE_NAME;
QString UserDefineConstant::DATA_BASE_NAME = "infosystem.db";
QString UserDefineConstant::DATA_BASE_HOST_NAME = "localhost";
int UserDefineConstant::DATA_BASE_PORT = 3306;
QString UserDefineConstant::DATA_BASE_USER_NAME = "root";
QString UserDefineConstant::DATA_BASE_PASS_WORD = "root";
bool UserDefineConstant::PROJECT_FIRST_START_LOAD_DEFAULT_TABLE_DATA = true;
//--------------------------------------------------------------------------------------------------------------------------------------------------------------



// -----------------------------------------自定义窗口组件相关----------------------------------------------------------------------------------------------

UserDefineWidget::UserDefineWidget(QWidget *parent) : QWidget(parent)
{
    this->parent = parent;
}

UserDefineWidget::~UserDefineWidget()
{

}

// ==============窗口尺寸变化事件=====================
void UserDefineWidget::resizeEvent(QResizeEvent *event)
{
    // 当窗口改变大小改变时自动调整表格大小
    autoAdjustmentTableWidth();
}

// ==============绘制事件============================
void UserDefineWidget::paintEvent(QPaintEvent *event)
{
    if(isWindowHasStarted) {
        return;
    }
    // 当窗口初始化绘制时改变表格大小
    autoAdjustmentTableWidth();

    // 改变isWidowSatrtAdjustmentTable为true,则后续的绘制事件就会在上一步被拦截，不进行表格处理，我们要的是在初始化时对表格进行一个自适应适配
    //，但是如果在构造函数里面处理则不行，因为构造函数中获取的全是初始值，不是调整过后的组件大小和参数
    // 构造函数里面只是在准备对象，也就是准备属性设置的参数等操作，绘制时才去读取我们在构造时设置的一些参数，在进行界面的绘制
    // 真正的改变其实是在绘制之后，所以我们要在绘制里面来处里对表格初始设置才能有效果
    changeWindowHasStartedStatus(true);
}

// ==============自动调整本窗口中表格的列宽=============================================
void UserDefineWidget::autoAdjustmentTableWidth()
{
    // 自动调整表格的宽度，查找该组件下的所有表格，进行自动调整宽度处理
    QList<QTableWidget*> tableWidgetList = this->findChildren<QTableWidget*>();
    for(int i = 0; i < tableWidgetList.size(); i++) {
        QTableWidget* widget = tableWidgetList.at(i);
        // 默认的自动调整列宽的配置参数
        QMap<int,int> columnWidthMap;
        columnWidthMap.insert(0,100);
        TableWidgetOpt::autoAdjustmentQTableWidgetWidth(widget,800,120, columnWidthMap);
    }
}

// ==============设置起动时是否已经调整过表格（isWindowHasStarted的值）==================
void UserDefineWidget::changeWindowHasStartedStatus(bool status)
{
    this->isWindowHasStarted = status;
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------


//--------------------------------------------------数据库管理相关------------------------------------------------------------------------------------------------
QSqlDatabase DataBaseManage::db = QSqlDatabase::database();

QSqlDatabase DataBaseManage::getDb()
{
    return DataBaseManage::db;
}

void DataBaseManage::openDb()
{
    // qt要成功使用mysql，请参考：https://blog.csdn.net/IT_CREATE/article/details/119155290?spm=1001.2014.3001.5501

    if(UserDefineConstant::DATA_BASE_DRIVE_NAME == UserDefineConstant::SQL_DRIVE_MYSQL_NAME) {
        // 连接mysql,如果mysql已经存在了相应数据库的名字，则可以setDatabaseName再open打开连接数据库
        // 如果没有，想要系统去创建数据库，则setDatabaseName不要设置，open打开时这样连接不上,因为没有相应数据库
        // 而是先连接上mysql，通过命令创建数据库，再通过命令使用相应数据库，切换到该数据库上面
        db = QSqlDatabase::addDatabase("QMYSQL");
        db.setHostName(UserDefineConstant::DATA_BASE_HOST_NAME); // 输入连接的数据库IP
        db.setPort(UserDefineConstant::DATA_BASE_PORT); // 输入连接的数据库端口
        db.setUserName(UserDefineConstant::DATA_BASE_USER_NAME); //输入连接的用户名
        db.setPassword(UserDefineConstant::DATA_BASE_PASS_WORD); //输入连接的密码
        if(db.open()) {
            QString databaseName = UserDefineConstant::DATA_BASE_NAME;
            db.setDatabaseName(databaseName); // 数据库名称
            qInfo()<<"打开数据库成功";
            QSqlQuery query = DataBaseManage::getQuery();
            if(query.exec("create database "+databaseName + " DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci")) {
                qInfo()<<"创建数据库"+databaseName+"成功";
            } else {
                qCritical()<<"创建数据库"+databaseName+"失败";
            }

            if(query.exec("use "+databaseName)) {
                qInfo()<<"使用数据库"+databaseName+"成功";
            } else {
                qCritical()<<"使用数据库"+databaseName+"失败";
            }
        } else {
            qCritical()<<"打开数据库失败";
        }
    } else {
        db = QSqlDatabase::addDatabase("QSQLITE");
        db.setDatabaseName(UserDefineConstant::DATA_BASE_NAME);
        if(db.open())
        {
            qInfo()<<"打开数据库成功";
        } else {
            qCritical()<<"打开数据库失败";
        }
    }
}

QSqlQuery DataBaseManage::getQuery()
{
    return QSqlQuery(DataBaseManage::db);
}



//--------------------------------------------------数据库操作相关------------------------------------------------------------------------------------------------
// ==============创建表方法===============================================================
const bool DataBaseOpt::createTable(QString tableName, QList<QString> columnInfos)
{
    return createTable(tableName, columnInfos, false);
}

// ==============创建表方法===============================================================
const bool DataBaseOpt::createTable(QString tableName, QList<QString> columnInfos, bool columnInfosEmptyAlsoCreate)
{
    // 完整创建表语句（ create table tableName ID INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT, COLUMN1 TEXT,COLUMN2 TEXT......) ）
    if(ObjectUtil::isEmpty(tableName)) {
        qCritical()<<"创建表所需表名为空，不创建";
        return false;
    }
    if(!columnInfosEmptyAlsoCreate && ObjectUtil::isEmpty(columnInfos)) {
        qCritical()<<"创建表所需字段信息为空，不创建";
        return false;
    }
    QString primaryKeyStr = " INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT";
    if(UserDefineConstant::DATA_BASE_DRIVE_NAME == UserDefineConstant::SQL_DRIVE_MYSQL_NAME) {
        primaryKeyStr = " INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT";
    }
    QString sql = "create table "+tableName+"("+UserDefineConstant::ID_COLUMN_NUIQUE_NAME+primaryKeyStr;

    for(QString columnInfo: columnInfos) {
        sql =  sql + "," + columnInfo + " text";
    }
    sql = sql + ")";
    qInfo()<<"执行创表语句："<<sql;
    QSqlQuery query = DataBaseManage::getQuery();
    if(query.exec(sql))
    {
        qInfo()<<"创建"<<tableName<<"成功";
        return true;
    }
    qCritical()<<"创建"<<tableName<<"失败！表已存在或语句出错";
    return false;
}

// ==============删除指定表方法===============================================================
const bool DataBaseOpt::removeTable(QString tableName) {
    // 完整删除指定表语句（ALTER TABLE DROP TABLE tableName）
    if(ObjectUtil::isEmpty(tableName)) {
        qCritical()<<"删除表时指定表名为空，无法进行删除表操作";
        return false;
    }
    QString sql = "DROP TABLE "+tableName;
    qInfo()<<"执行删除表语句："<<sql;
    QSqlQuery query = DataBaseManage::getQuery();
    if(query.exec(sql))
    {
        qInfo()<<"删除"<<tableName<<"成功";
        return true;
    }
    qCritical()<<"删除"<<tableName<<"失败！表不存在或语句出错";
    return false;
}

// ==============重命名表名方法===============================================================
const bool DataBaseOpt::renameTable(QString oldTableName, QString newTableName) {
    // 完整重命名表名语句（ALTER TABLE oldTableName RENAME TO newTableName）
    if(ObjectUtil::isEmpty(oldTableName) || ObjectUtil::isEmpty(newTableName)) {
        qCritical()<<"重命名时，指定老表名或者新表名为空，无法重命名";
        return false;
    }
    QString renameSql = "ALTER TABLE "+oldTableName+" RENAME TO " + newTableName; // 将表重命名
    qInfo()<<"执行重命名表语句："<<renameSql;
    QSqlQuery query = DataBaseManage::getQuery();
    if(query.exec(renameSql))
    {
        qInfo()<<"重命名表"<<oldTableName<<"为"<<newTableName<<"成功";
        return true;
    }
    qCritical()<<"重命名表"<<oldTableName<<"为"<<newTableName<<"失败！表不存在或语句出错";
    return false;
}

// ==============将老表中的数据拷贝到新表中===============================================================
const bool DataBaseOpt::copyOldTableDataToNewTable(QString oldTableName, QList<QString> oldColumnNames, QString newTableName, QList<QString> newColumnNames){
    // 完整语句（insert into newTableName(newColumn1,newColumn2......) select oldColumn1,oldColumn2...... from oldTableName）
    if(ObjectUtil::isEmpty(oldTableName) || ObjectUtil::isEmpty(newTableName)) {
        qCritical()<<"拷贝表中数据时，指定老表名或者新表名为空，无法拷贝数据";
        return false;
    }
    if(ObjectUtil::isEmpty(oldColumnNames) || ObjectUtil::isEmpty(newColumnNames)) {
        qCritical()<<"拷贝表中数据时，指定老表列集合或者新表列集合为空，无法拷贝数据";
        return false;
    }
    // 拼接老的列查询语句（格式为：column1,Colum2,Colum3......）
    QString oldColumnSql = "";
    for(int i = 0; i<oldColumnNames.size(); i++) {
       if(i == oldColumnNames.size() -1) {
           oldColumnSql = oldColumnSql + oldColumnNames.at(i);
       } else {
           oldColumnSql = oldColumnSql + oldColumnNames.at(i) + ",";
       }
    }
    // 拼接新的列查询语句（格式为：column1,Colum2,Colum3......）
    QString newColumnSql = "";
    for(int i = 0; i<newColumnNames.size(); i++) {
       if(i == oldColumnNames.size() -1) {
           newColumnSql = newColumnSql + newColumnNames.at(i);
       } else {
           newColumnSql = newColumnSql + newColumnNames.at(i) + ",";
       }
    }
    QString sql = "insert into " + newTableName+ "(" +newColumnSql+ ") select " + oldColumnSql + " from " + oldTableName; // 将表重命名
    qInfo()<<"执行拷贝表数据语句："<<sql;
    QSqlQuery query = DataBaseManage::getQuery();
    if(query.exec(sql))
    {
        qInfo()<<"拷贝表数据"<<oldTableName<<"到"<<newTableName<<"成功";
        return true;
    }
    qCritical()<<"拷贝表数据"<<oldTableName<<"到"<<newTableName<<"失败！表不存在或语句出错";
    return false;
}

// ==============向指定表中增加列===============================================================
const bool DataBaseOpt::addColumnForTable(QString tableName, QList<QString> columnNames)
{
    // 完整语句（ALTER TABLE tableName ADD COLUMN column type,column2 type2......）
    if(ObjectUtil::isEmpty(tableName) || ObjectUtil::isEmpty(columnNames)) {
        return false;
    }
    QSqlQuery query = DataBaseManage::getQuery();
    bool isSucess = false;
    // 如果是mysql,走这条分支，用ALTER命令修改
    if(UserDefineConstant::DATA_BASE_DRIVE_NAME == UserDefineConstant::SQL_DRIVE_MYSQL_NAME) { // mysql分支，支持一次性新增多列
        QString addColumnSql = "";
        int i = 0;
        for(QString column: columnNames) {
            if(i == columnNames.size() -1) {
                addColumnSql = addColumnSql + " ADD COLUMN " + column + " text";
            } else {
                addColumnSql = addColumnSql + " ADD COLUMN " + column + " text" + ",";
            }
            i++;
        }
        QString sql = "ALTER TABLE " + tableName + addColumnSql;
        qInfo()<<"执行添加表列语句："<<sql;
        if(query.exec(sql))
        {
            qInfo()<<"添加列"<<tableName<<":"<<columnNames<<"成功";
            isSucess = true;
        } else{
            qCritical()<<"添加列"<<tableName<<":"<<columnNames<<"失败";
        }
    } else { //sqllite分支，一次只支持一列插入
        QList<bool> sucessStatus;
        for(QString column: columnNames) {
            QString sql = "ALTER TABLE " + tableName + " ADD COLUMN " + column + " text";
            qInfo()<<"执行添加表列语句："<<sql;
            bool nowSucess = query.exec(sql);
            sucessStatus.append(nowSucess);
            if(nowSucess)
            {
                qInfo()<<"添加列"<<tableName<<":"<<column<<"成功";
            } else{
                qCritical()<<"添加列"<<tableName<<":"<<column<<"失败";
            }
        }

        // 所有的sql执行成功与否结果存在集合中，只要有一个错误，就是直接返回失败信息（注：数据库事务交给该方法的调用方去控制）
        if(!sucessStatus.contains(false))
        {
            qInfo()<<"添加所选列"<<tableName<<":"<<columnNames<<"成功";
            isSucess = true;
        }
        else
            qCritical()<<"添加所选列"<<tableName<<":"<<columnNames<<"失败";

    }
    return isSucess;
}

// ==============修改指定表的列===============================================================
const bool DataBaseOpt::updateColumnForTable(QString tableName, QMap<QString, QString> oldColumnNameAndNewColumnName)
{
    if(ObjectUtil::isEmpty(tableName) || ObjectUtil::isEmpty(oldColumnNameAndNewColumnName)) {
        return false;
    }
    QSqlQuery query = DataBaseManage::getQuery();
    bool isSucess = false;
    // 如果是mysql,走这条分支，用ALTER命令修改
    if(UserDefineConstant::DATA_BASE_DRIVE_NAME == UserDefineConstant::SQL_DRIVE_MYSQL_NAME) { // mysql分支，支持一次性修改多列名称
        // 完整修改列名语句（ALTER TABLE tableName change oldColumn newColumn type,change oldColumn2 newColumn2 type2......）
        QString updatColumnSql = "";
        QList<QString> oldColumns = oldColumnNameAndNewColumnName.keys();
        int i = 0;
        for(QString oldColumn: oldColumns) {
            QString newColumn = oldColumnNameAndNewColumnName.value(oldColumn);
            if(i == oldColumns.size() -1) {
                updatColumnSql = updatColumnSql + " change " + oldColumn + " " + newColumn + " text";
            } else {
                updatColumnSql = updatColumnSql + " change " + oldColumn + " " + newColumn + " text" + ",";
            }
            i++;
        }
        QString sql = "ALTER TABLE " + tableName + updatColumnSql;
        qInfo()<<"执行修改表列名语句："<<sql;
        if(query.exec(sql))
        {
            qInfo()<<"修改列"<<tableName<<":"<<oldColumns<<"->"<<oldColumnNameAndNewColumnName.values()<<"成功";
            isSucess = true;
        } else {
            qCritical()<<"修改列"<<tableName<<":"<<oldColumns<<"->"<<oldColumnNameAndNewColumnName.values()<<"失败";
        }
    } else { // 如果是sqllite走这个分支，sqllite不支持ALTER修改命令
        QList<QueryConditions> columnConditions;
        columnConditions.append(QueryConditions(UserDefineConstant::TABLE_CONNECT_TABLE, tableName, false, "=", "and"));
        QList<ColumnEntity> columnEntitys = DataBaseOpt::selectAllColumnTable(columnConditions); // 查询出对应表的所有字段信息
        QList<QString> oldColumns; // 老列名集合
        QList<QString> newColumns; // 修改后新的列名集合
        // 组装原表列名集合，和修改后的列名集合
        for(ColumnEntity entity: columnEntitys) {
            oldColumns.append(entity.columnName);
            if(oldColumnNameAndNewColumnName.contains(entity.columnName)) {
                newColumns.append(oldColumnNameAndNewColumnName.value(entity.columnName));
            } else {
                newColumns.append(entity.columnName);
            }
        }
        QList<bool> sucessStatus;
        QString tempTable = tableName + "_temp";
        sucessStatus.append(DataBaseOpt::renameTable(tableName, tempTable)); // 执行重命名原表为临时表, 将表重命名为临时表“'原表名'+'_temp'”
        sucessStatus.append(DataBaseOpt::createTable(tableName, newColumns, false)); // 创建同原表相同表名的新表（修改了列名的新表）
        sucessStatus.append(DataBaseOpt::copyOldTableDataToNewTable(tempTable, oldColumns, tableName, newColumns)); // 将临时表的数据拷贝到新表中
        sucessStatus.append(DataBaseOpt::removeTable(tempTable)); // 删除临时表

        // 所有的sql执行成功与否结果存在集合中，只要有一个错误，就是直接返回失败信息（注：数据库事务交给该方法的调用方去控制）
        if(!sucessStatus.contains(false))
        {
            qInfo()<<"修改列"<<tableName<<":"<<oldColumns<<"->"<<newColumns<<"成功";
            isSucess = true;
        }
        else
            qCritical()<<"修改列"<<tableName<<":"<<oldColumns<<"->"<<newColumns<<"失败";

    }
    return isSucess;
}

// ==============删除指定表的列===============================================================
const bool DataBaseOpt::deleteColumnForTable(QString tableName, QList<QString> columnNames)
{
    if(ObjectUtil::isEmpty(tableName) || ObjectUtil::isEmpty(columnNames)) {
        return false;
    }
    QSqlQuery query = DataBaseManage::getQuery();
    bool isSucess = false;
    if(UserDefineConstant::DATA_BASE_DRIVE_NAME == UserDefineConstant::SQL_DRIVE_MYSQL_NAME) { // mysql分支，支持一次性删除多列
        // 完整删除列语句（alter table tableName drop column column1,drop column column2......;）
        // 拼接删除列语句（格式为：drop column column1,drop column Colum2,drop column Colum3......）
        QString columnSql = "";
        for(int i = 0; i<columnNames.size(); i++) {
           if(i == columnNames.size() -1) {
               columnSql = columnSql + " drop column " + columnNames.at(i);
           } else {
               columnSql = columnSql + " drop column " + columnNames.at(i) + ",";
           }
        }
        QString sql = "ALTER TABLE "+tableName + columnSql;
        qInfo()<<"执行删除表列语句："<<sql;
        if(query.exec(sql))
        {
            qInfo()<<"删除列"<<tableName<<":"<<columnSql<<"成功";
            isSucess = true;
        } else{
            qCritical()<<"删除列"<<tableName<<":"<<columnSql<<"失败";
        }
    } else {// SQLLITE分支，因为不支持alter删除语句，所以采用以下方式实现
        // 完整删除列语句（alter table tableName drop column column1;）
        QList<QueryConditions> columnConditions;
        columnConditions.append(QueryConditions(UserDefineConstant::TABLE_CONNECT_TABLE, tableName, false, "=", "and"));
        QList<ColumnEntity> columnEntitys = DataBaseOpt::selectAllColumnTable(columnConditions); // 查询出对应表的所有字段信息
        QList<QString> oldColumns; // 老列名集合
        QList<QString> newColumns; // 删除指定列后新的列名集合
        // 组装原表列名集合，和删除指定列后的列名集合
        for(ColumnEntity entity: columnEntitys) {
            oldColumns.append(entity.columnName);
            // 如果列名不存在需要被删列名集合中，则将该列名装进新的集合中（筛选出删除指定列后剩下的列集合）
            if(!columnNames.contains(entity.columnName)) {
                newColumns.append(entity.columnName);
            }
        }
        QList<bool> sucessStatus;
        QString tempTable = tableName + "_temp";
        sucessStatus.append(DataBaseOpt::renameTable(tableName, tempTable)); // 执行重命名原表为临时表, 将表重命名为临时表“'原表名'+'_temp'”
        sucessStatus.append(DataBaseOpt::createTable(tableName, newColumns, true)); // 创建同原表相同表名的新表（修改了列名的新表）
        // 在删除指定列后剩下的列不为空才进行拷贝
        if (!ObjectUtil::isEmpty(newColumns)) {
          sucessStatus.append(DataBaseOpt::copyOldTableDataToNewTable(tempTable, oldColumns, tableName, newColumns)); // 将临时表的数据拷贝到新表中
        }
        sucessStatus.append(DataBaseOpt::removeTable(tempTable)); // 删除临时表

        // 所有的sql执行成功与否结果存在集合中，只要有一个错误，就是直接返回失败信息（注：数据库事务交给该方法的调用方去控制）
        if(!sucessStatus.contains(false))
        {
            qInfo()<<"删除所选列"<<tableName<<":"<<columnNames<<"成功";
            isSucess = true;
        }
        else
            qCritical()<<"删除所选列"<<tableName<<":"<<columnNames<<"失败";
    }
    return isSucess;
}

// ==============修改表的名字===============================================================
const bool DataBaseOpt::updateTableName(QMap<QString, QString> oldTableNameAndNewTableName)
{
    // 完整修改表的名字语句（alter table tableName RENAME TO newTableName;）
    if(ObjectUtil::isEmpty(oldTableNameAndNewTableName)) {
        qCritical()<<"修改表时，没有旧表名和老表名映射关系，不能进行表名修改";
        return false;
    }
    QSqlQuery query = DataBaseManage::getQuery();
    bool isSucess = false;

    QList<bool> sucessStatus;
    QList<QString> oldTables = oldTableNameAndNewTableName.keys();
    for(QString oldTable: oldTables) {
        QString newTable = oldTableNameAndNewTableName.value(oldTable);
        QString sql = "ALTER TABLE "+oldTable+" RENAME TO "+newTable;
        qInfo()<<"执行修改表名语句："<<sql;
        bool nowSucess = query.exec(sql);// 执行语句
        sucessStatus.append(nowSucess);
        if(nowSucess)
        {
            qInfo()<<"修改表名:"<<oldTable<<"->"<<newTable<<"成功";
        } else {
            qCritical()<<"修改表名:"<<oldTable<<"->"<<newTable<<"失败";
        }
    }

    // 所有的sql执行成功与否结果存在集合中，只要有一个错误，就是直接返回失败信息（注：数据库事务交给该方法的调用方去控制）
    if(!sucessStatus.contains(false))
    {
        qInfo()<<"修改所选表名:"<<oldTables<<"->"<<oldTableNameAndNewTableName.values()<<"成功";
        isSucess = true;
    }
    else
        qCritical()<<"修改所选表名:"<<oldTables<<"->"<<oldTableNameAndNewTableName.values()<<"失败";

    return isSucess;
}

// ==============根据条件查询数据总数===============================================================
const int DataBaseOpt::selectAllCount(QString tableName, QList<QueryConditions> conditions)
{
    // 完整语句（select count(1) from tableName WHERE ......;）
    if(ObjectUtil::isEmpty(tableName)) {
        return 0;
    }
    QString countSql = "select count(1) from " + tableName;
    if(conditions.size() != 0) {
        countSql = countSql + " where " + getWhere(conditions);
    }
    qInfo()<<"执行查询总数语句："<<countSql;
    QSqlQuery query = DataBaseManage::getQuery();
    query.exec(countSql);
    int allCount = 0;
    // 查询总条数
    while(query.next()) {
        allCount = query.value(0).toInt();
    }
    return allCount;
}

// ==============根据条件查询数据库数据===============================================================
const QList<QMap<QString, QString>> DataBaseOpt::selectTable(QString tableName, QList<QString> columnNames, QList<QueryConditions> conditions)
{
    // 完整查询语句（select ID,COLUMN1,COLUMN2...... from tableName WHERE ......;）
    if(ObjectUtil::isEmpty(tableName) || ObjectUtil::isEmpty(columnNames)) {
        return QList<QMap<QString, QString>>();
    }
    // 查询具体参数
    QString sql = "select ";
    if(!columnNames.contains(UserDefineConstant::ID_COLUMN_NUIQUE_NAME)) {
        columnNames.insert(0, UserDefineConstant::ID_COLUMN_NUIQUE_NAME);
    }
    int index = 0;
    for(QString columnName: columnNames) {
        if(index == columnNames.size() -1) {
            sql = sql + columnName;
        } else {
            sql = sql + columnName + ",";
        }
        index++;
    }
    sql = sql + " from " + tableName;
    if(conditions.size() != 0) {
        sql = sql + " where " + getWhere(conditions);
    }
    qInfo()<<"执行查询语句："<<sql;
    QSqlQuery query = DataBaseManage::getQuery();
    query.exec(sql);
    QList<QMap<QString, QString>> result;
    int count = 0;
    while(query.next()) {
        QMap<QString, QString> rowData;
        QString info = "";
        int table_column = 0;
        for(QString columnName : columnNames) {
            QString value = query.value(table_column).toString();
            rowData.insert(columnName, value);
            info = info + columnName +":"+value + "|";
            table_column++;
        }
        result.append(rowData);
        qInfo()<<"查询数据"+QString::number(count)<<":"<<info;
        count++;
    }
    return result;
}

// ==============通过id查询修改数据库数据===============================================================
const bool DataBaseOpt::updateTableById(QString tableName, int id, QMap<QString, QString> columnNameAndValues)
{
    // 完整语句（UPDATE tableName COLUMN1=?,COLUMN2=?...... WHERE ID = ?;）
    if(ObjectUtil::isEmpty(tableName)) {
        qCritical()<<"进行修改表数据时没有指定表名";
        return false;
    }
    if(ObjectUtil::isEmpty(columnNameAndValues)) {
        qCritical()<<"进行修改表"<<tableName<<"数据时没有指定修改哪些列数据";
        return false;
    }
    if(id < 0) {
        qCritical()<<"进行修改表"<<tableName<<"数据时，指定的id小于0";
        return false;
    }
    QString sql = "update " + tableName +" set "+getSet(columnNameAndValues)+" where "+UserDefineConstant::ID_COLUMN_NUIQUE_NAME+"=" + QString::number(id);
    qInfo()<<"执行修改语句："<<sql;
    QSqlQuery query = DataBaseManage::getQuery();
    if(query.exec(sql)) {
        qInfo()<<"进行修改数据：成功|"<< columnNameAndValues;
        return true;
    }
    qCritical()<<"进行修改数据：失败|"<< columnNameAndValues;
    return false;
}

// ==============向数据库中插入数据===============================================================
const bool DataBaseOpt::insertTableData(QString tableName, QList<QPair<QString,QString>> columnNameAndValues)
{
    // 完整插入语句（INSERT INTO tableName (COLUMN1,COLUMN2......) VALUES(VALUE1,VALUE2......)）
    if(ObjectUtil::isEmpty(tableName)) {
        qCritical()<<"进行插入表数据时没有指定表名";
        return false;
    }
    if(ObjectUtil::isEmpty(columnNameAndValues)) {
        qCritical()<<"进行插入表"<<tableName<<"数据时没有指定插入哪些列数据";
        return false;
    }
    QString sql = "INSERT INTO " + tableName +"(";
    int index = 0;
    for(QPair<QString,QString> column: columnNameAndValues) {
        if(index == columnNameAndValues.size() -1) {
            sql = sql + column.first;
        } else {
            sql = sql + column.first+",";
        }
        index++;
    }
    sql = sql + ") values (";
    int index2 = 0;
    for(QPair<QString,QString> column: columnNameAndValues) {
        if(index2 == columnNameAndValues.size() -1) {
            sql = sql +"\"" +column.second+"\"";
        } else {
            sql = sql +"\"" +column.second+"\",";
        }
        index2++;
    }
    sql = sql + ")";
    qInfo()<<"执行插入语句："<<sql;
    QSqlQuery query = DataBaseManage::getQuery();
    if(query.exec(sql)) {
        qInfo()<<"进行插入数据成功|" << columnNameAndValues;
        return true;
    }
    qCritical()<<"进行插入数据失败|" << columnNameAndValues;
    return false;
}

// ==============根据条件修改数据库中的数据===============================================================
const bool DataBaseOpt::updateTableDataByCondition(QString tableName, QMap<QString, QString> columnNameAndValues, QList<QueryConditions> conditions) {
    // 完整语句（UPDATE tableName COLUMN1=?,COLUMN2=?...... WHERE ......;）
    if(ObjectUtil::isEmpty(tableName)) {
        qCritical()<<"进行修改表数据时没有指定表名";
        return false;
    }
    if(ObjectUtil::isEmpty(columnNameAndValues)) {
        qCritical()<<"进行修改表"<<tableName<<"数据时没有指定修改哪些列数据";
        return false;
    }
    if(ObjectUtil::isEmpty(conditions)) {
        qWarning()<<"进行修改表"<<tableName<<"数据时没有指定条件，将修改所有数据";
    }
    QString sql = "update " + tableName +" set " + getSet(columnNameAndValues);
    if(!ObjectUtil::isEmpty(conditions)) {
        sql = sql +" where " + getWhere(conditions);
    }
    qInfo()<<"执行修改语句："<<sql;
    QSqlQuery query = DataBaseManage::getQuery();
    if(query.exec(sql)) {
        qInfo()<<"进行修改数据：成功|"<< columnNameAndValues;
        return true;
    }
    qCritical()<<"进行修改数据：失败|"<< columnNameAndValues;
    return false;
}

// ==============根据条件删除表数据===============================================================
const bool DataBaseOpt::deleteTableDataByCondition(QString tableName, QList<QueryConditions> conditions) {
    // 完整删除语句（delete from tableName where ......）
    if(ObjectUtil::isEmpty(tableName)) {
        qCritical()<<"进行删除表数据时没有指定表名";
        return false;
    }
    if(ObjectUtil::isEmpty(conditions)) {
        qWarning()<<"进行删除表"<<tableName<<"数据时没有指定条件，将删除所有数据";
    }
    QString sql = "delete from " + tableName;
    if(!ObjectUtil::isEmpty(conditions)) {
        sql = sql + " where " + getWhere(conditions);
    }
    qInfo()<<"执行删除语句："<<sql;
    QSqlQuery query = DataBaseManage::getQuery();
    if(query.exec(sql)) {
        qInfo()<<"删除成功";
        return true;
    }
    qCritical()<<"删除失败";
    return false;
}

// ==============根据id集合删除表数据===============================================================
const bool DataBaseOpt::removeTableByIds(QString tableName, QList<int> ids)
{
    // 完整删除语句（delete from tableName where ......）
    if(ObjectUtil::isEmpty(tableName) || ObjectUtil::isEmpty(ids)) {
        return false;
    }
    QString sql = "delete from " + tableName +" where "+UserDefineConstant::ID_COLUMN_NUIQUE_NAME+" in(";
    int index = 0;
    for(int id: ids) {
        if(index == ids.size() -1) {
            sql = sql + QString::number(id);
        } else {
            sql = sql + QString::number(id) +",";
        }
        index++;
    }
    sql = sql + ")";
    qInfo()<<"执行删除语句："<<sql;
    QSqlQuery query = DataBaseManage::getQuery();
    if(query.exec(sql)) {
        qInfo()<<"删除成功";
        return true;
    }
    qCritical()<<"删除失败";
    return false;
}

// ==============获取sql中修改数据时的set对应的语句===============================================================
const QString DataBaseOpt::getSet(QMap<QString, QString> columnNameAndValues)
{
    // 完整set语句：set column1=value1,column2=value2 ......
    if(columnNameAndValues.size() == 0) {
        return "";
    }
    QList<QString> columnNames = columnNameAndValues.keys();
    int index = 0;
    QString set = "";
    for(QString columnName: columnNames) {
        if(index == columnNames.size() -1) {
            set = set + columnName+"=\""+columnNameAndValues.value(columnName)+"\"";
        } else {
            set = set + columnName+"=\""+columnNameAndValues.value(columnName)+"\",";
        }
        index++;
    }
    return set;
}

// ==============获取sql的where条件语句===============================================================
const QString DataBaseOpt::getWhere(QList<QueryConditions> conditions)
{
    // 完整where语句：where column1=number1 and column2='value2' or column3 like '%value3%' ......
    if(conditions.size() == 0) {
        return "";
    }
    int index = 0;
    QString where = "";
    for(QueryConditions condition: conditions) {
        QString relationshipParam = "and";
        // 如果连接符号是and或者or,则进行相应的连接符设置赋值，否则直接使用默认的and连接符
        if(condition.connectionSymbol.toLower() == "and" || condition.connectionSymbol.toLower() == "or") {
            relationshipParam = condition.connectionSymbol.toLower();
        }
        if(index == conditions.size() -1) { // 这里表示最后一条数据条件的处理，最后不会拼接and 或者 or ,也就是【name = "小明" and age = 15 and hobbi = "打篮球"】 这种格式
            if(!ObjectUtil::isEmpty(condition.userDefinejudgment)) { // 如果自定义查询条件不为空，则直接使用自定义查询条件
                where = condition.userDefinejudgment + " ";
            } else {
                if(condition.judgmentSymbol.toLower() == "like%") {
                    where = where + condition.columnName+" LIKE \""+condition.columnValue+"%\" ";
                }else if(condition.judgmentSymbol.toLower() == "%like") {
                    where = where + condition.columnName+" LIKE \"%"+condition.columnValue+"\" ";
                } else if(condition.judgmentSymbol.toLower() == "%like%") {
                    where = where + condition.columnName+" LIKE \"%"+condition.columnValue+"%\" ";
                } else {
                    QString value = condition.columnValue;
                    if(!condition.isNumber) { // 这样处理是因为数字不用引号包裹，但是其他的比如字符串、时间格式都需要引号进行包裹
                        value = "\"" + value + "\"";
                    }
                    where = where + condition.columnName+" "+condition.judgmentSymbol+" "+value+" ";
                }
            }
        } else { // 最后一条之前的所有的数据的处理，最后之前的都要在条件拼接后加上and 或者 or ,也就是【name = "小明" and age = 15 and】 这种格式
            if(!ObjectUtil::isEmpty(condition.userDefinejudgment)) {
                where = condition.userDefinejudgment + relationshipParam + " ";
            } else {
                if(condition.judgmentSymbol.toLower() == "like%") {
                    where = where + condition.columnName+" LIKE \""+condition.columnValue+"%\" "+ relationshipParam + " ";
                }else if(condition.judgmentSymbol.toLower() == "%like") {
                    where = where + condition.columnName+" LIKE \"%"+condition.columnValue+"\" "+ relationshipParam + " ";
                } else if(condition.judgmentSymbol.toLower() == "%like%") {
                    where = where + condition.columnName+" LIKE \"%"+condition.columnValue+"%\" "+ relationshipParam + " ";
                } else {
                    QString value = condition.columnValue;
                    if(!condition.isNumber) {
                        value = "\"" + value + "\"";
                    }
                    where = where + condition.columnName+" "+condition.judgmentSymbol+" "+value+" "+ relationshipParam + " ";
                }
            }
        }
        index++;
    }
    return where;
}

// ==============根据页码和单页数据量获取数据库对应起始索引===============================================================
const int DataBaseOpt::getStartIndex(int page, int size)
{
    return (page - 1)* size;
}

// ==============创建自定义表===============================================================
const bool DataBaseOpt::createUserDefineSqlTable()
{
     QList<QString> columnInfos;
     // 表名称
     columnInfos.append(UserDefineConstant::USERDEFINE_TABLE_COLUMN_TABLE_NAME);
     // 表的中文名称
     columnInfos.append(UserDefineConstant::USERDEFINE_TABLE_COLUMN_TABLE_ZN_NAME);
     return DataBaseOpt::createTable(UserDefineConstant::USERDEFINE_TABLE_TABLE_NAME, columnInfos);
}

// ==============根据查询条件获取自定义表里的所有数据===============================================================
const QList<UserDefineTableEntity> DataBaseOpt::selectAllUserDefineTable(QList<QueryConditions> conditions)
{
    QSqlQuery query = DataBaseManage::getQuery();
    // ----------------------------组装完整的select查询语句开始------------------------
    QString sql = "select "+UserDefineConstant::ID_COLUMN_NUIQUE_NAME+","
            +UserDefineConstant::USERDEFINE_TABLE_COLUMN_TABLE_NAME+","
            +UserDefineConstant::USERDEFINE_TABLE_COLUMN_TABLE_ZN_NAME
            +" from "+UserDefineConstant::USERDEFINE_TABLE_TABLE_NAME;
    if(conditions.size() != 0) {
        sql = sql + " where " + getWhere(conditions);
    }
    qInfo()<<"查询自定义表语句："<<sql;
    // ----------------------------组装完整的select查询语句开始------------------------
    query.exec(sql);
    QList<UserDefineTableEntity> userdefineTableEntitys;
    while(query.next())
    {
        UserDefineTableEntity userDefineTableEntity;
        userDefineTableEntity.id = query.value(0).toInt();
        userDefineTableEntity.tableName = query.value(1).toString();
        userDefineTableEntity.tableZnName = query.value(2).toString();
        userdefineTableEntitys.append(userDefineTableEntity);
        qInfo()<<"查询自定义表字段数据："<<UserDefineConstant::ID_COLUMN_NUIQUE_NAME+"="<<userDefineTableEntity.id
               <<","+UserDefineConstant::USERDEFINE_TABLE_COLUMN_TABLE_NAME+"="<<userDefineTableEntity.tableName
              <<","+UserDefineConstant::USERDEFINE_TABLE_COLUMN_TABLE_ZN_NAME+"="<<userDefineTableEntity.tableZnName;
    }
    qInfo()<<"查询自定义表字段数据总量："<<userdefineTableEntitys.size();
    return userdefineTableEntitys;
}

// ==============通过id集合查询自定义表里的数据===============================================================
const QList<UserDefineTableEntity> DataBaseOpt::selectUserDefineTableByIds(QList<int> ids)
{
    QList<UserDefineTableEntity> userDefineTableEntitys;
    if(ids.size() == 0) {
        return userDefineTableEntitys;
    }
    // ----------------------------组装完整的select查询语句开始------------------------
    // 组装查询条件中的in条件开始
    QString sql = "(";
    int index = 0;
    for(int id:ids) {
        if(index == ids.size()-1) {
            sql = sql + QString::number(id);
        } else {
            sql = sql + QString::number(id) + ",";
        }
        index++;
    }
    sql = sql + ")";
    // 组装查询条件中的in条件结束
    sql = "select "+UserDefineConstant::ID_COLUMN_NUIQUE_NAME+","
            +UserDefineConstant::USERDEFINE_TABLE_COLUMN_TABLE_NAME+","
            +UserDefineConstant::USERDEFINE_TABLE_COLUMN_TABLE_ZN_NAME
            +" from "+UserDefineConstant::USERDEFINE_TABLE_TABLE_NAME+" where "+UserDefineConstant::ID_COLUMN_NUIQUE_NAME+" in "+sql;
    qInfo()<<"查询自定义表信息语句:"<< sql;
    // ----------------------------组装完整的select查询语句开始------------------------
    QSqlQuery query = DataBaseManage::getQuery();
    query.exec(sql);
    while(query.next()) {
        UserDefineTableEntity userDefineTableEntity;
        userDefineTableEntity.id = query.value(0).toInt();
        userDefineTableEntity.tableName = query.value(1).toString();
        userDefineTableEntity.tableZnName = query.value(2).toString();
        userDefineTableEntitys.append(userDefineTableEntity);
    }
    return userDefineTableEntitys;
}

// ==============创建自定义字段表===============================================================
const bool DataBaseOpt::createColumnSqlTable()
{
    QList<QString> columnInfos;
    // 关联表
    columnInfos.append(UserDefineConstant::TABLE_CONNECT_TABLE);
    // 字段名
    columnInfos.append(UserDefineConstant::TABLE_COLUMN_NAME);
    // 字段中文显示名
    columnInfos.append(UserDefineConstant::TABLE_COLUMN_ZN_NAME);
    // 是否唯一
    columnInfos.append(UserDefineConstant::TABLE_COLUMN_IS_UNIQUE);
    // 是否必填
    columnInfos.append(UserDefineConstant::TABLE_COLUMN_IS_REQUIRED);
    return DataBaseOpt::createTable(UserDefineConstant::COLUMN_TABLE_NAME, columnInfos);
}

// ==============根据查询条件获取自定义字段表里的所有数据===============================================================
const QList<ColumnEntity> DataBaseOpt::selectAllColumnTable(QList<QueryConditions> conditions)
{
    QSqlQuery query = DataBaseManage::getQuery();
    // ----------------------------组装完整的select查询语句开始------------------------
    QString sql = "select "+UserDefineConstant::ID_COLUMN_NUIQUE_NAME+","
            +UserDefineConstant::TABLE_CONNECT_TABLE+","
            +UserDefineConstant::TABLE_COLUMN_NAME+","
            +UserDefineConstant::TABLE_COLUMN_ZN_NAME+","
            +UserDefineConstant::TABLE_COLUMN_IS_UNIQUE+","
            +UserDefineConstant::TABLE_COLUMN_IS_REQUIRED
            +" from "+UserDefineConstant::COLUMN_TABLE_NAME;
    if(conditions.size() != 0) {
        sql = sql + " where " + getWhere(conditions);
    }
    qInfo()<<"查询自定义字段表语句："<<sql;
    // ----------------------------组装完整的select查询语句结束------------------------
    query.exec(sql);
    QList<ColumnEntity> columnEntitys;
    while(query.next())
    {
        ColumnEntity columnEntity;
        columnEntity.id = query.value(0).toInt();
        columnEntity.connectTable = query.value(1).toString();
        columnEntity.columnName = query.value(2).toString();
        columnEntity.columnZnName = query.value(3).toString();
        columnEntity.columnIsUnique = query.value(4).toString();
        columnEntity.columnIsRequired =  query.value(5).toString();
        columnEntitys.append(columnEntity);
        qInfo()<<"查询字段数据："<<UserDefineConstant::ID_COLUMN_NUIQUE_NAME+"="<<columnEntity.id
               <<","+UserDefineConstant::TABLE_COLUMN_NAME+"="<<columnEntity.connectTable
              <<","+UserDefineConstant::TABLE_COLUMN_NAME+"="<<columnEntity.columnName
             <<","+UserDefineConstant::TABLE_COLUMN_ZN_NAME+"="<<columnEntity.columnZnName
            <<","+UserDefineConstant::TABLE_COLUMN_IS_UNIQUE+"="<<columnEntity.columnIsUnique
           <<","+UserDefineConstant::TABLE_COLUMN_IS_REQUIRED+"="<<columnEntity.columnIsRequired;
    }
    qInfo()<<"查询字段数据总量："<<columnEntitys.size();
    return columnEntitys;
}

// ==============通过id集合查询自定义字段表里的数据===============================================================
const QList<ColumnEntity> DataBaseOpt::selectColumnTableByIds(QList<int> ids)
{
    QList<ColumnEntity> columnEntitys;
    if(ids.size() == 0) {
        return columnEntitys;
    }
    // ----------------------------组装完整的select查询语句开始------------------------
    // 组装查询条件中的in条件开始
    QString sql = "(";
    int index = 0;
    for(int id:ids) {
        if(index == ids.size()-1) {
            sql = sql + QString::number(id);
        } else {
            sql = sql + QString::number(id) + ",";
        }
        index++;
    }
    sql = sql + ")";
    // 组装查询条件中的in条件结束
    sql = "select "+UserDefineConstant::ID_COLUMN_NUIQUE_NAME+","
            +UserDefineConstant::TABLE_CONNECT_TABLE+","
            +UserDefineConstant::TABLE_COLUMN_NAME+","
            +UserDefineConstant::TABLE_COLUMN_ZN_NAME+","
            +UserDefineConstant::TABLE_COLUMN_IS_UNIQUE+","
            +UserDefineConstant::TABLE_COLUMN_IS_REQUIRED
            +" from "+UserDefineConstant::COLUMN_TABLE_NAME+" where "+UserDefineConstant::ID_COLUMN_NUIQUE_NAME+" in "+sql;
    qInfo()<<"查询自定义字段表信息语句:"<< sql;
    // ----------------------------组装完整的select查询语句结束------------------------
    QSqlQuery query = DataBaseManage::getQuery();
    query.exec(sql);
    while(query.next()) {
        ColumnEntity columnEntity;
        columnEntity.id = query.value(0).toInt();
        columnEntity.connectTable = query.value(1).toString();
        columnEntity.columnName = query.value(2).toString();
        columnEntity.columnZnName = query.value(3).toString();
        columnEntity.columnIsUnique = query.value(4).toString();
        columnEntity.columnIsRequired = query.value(5).toString();
        columnEntitys.append(columnEntity);
    }
    return columnEntitys;
}

//--------------------------------------------------------------------------------------------------------------------------------------------------------------




//--------------------------------------------------表格组件操作相关-----------------------------------------------------------------------------------------------

// ==============获得表格选中行的id列的值集合===============================================================
const QList<int> TableWidgetOpt::getQTableWidgetCheckedIds(QTableWidget *widget)
{
    // 循环查找列表头，如果列表头名称是主键（id）,则记录下索引值,也就是id列的索引值
    int idColumn = findQTableWidgetIdZnNameColumn(widget);
    // 循环每行数据，通过id列索引值找出id对应单元格数据，也就是id值
    // 判断是否选中，只有选中状态行的id值才记录下来
    int rowCount = widget->rowCount();
    QList<int> ids;
    for(int row = 0;row<rowCount;row++) {
        // 第一列是选择栏（含复选框的列）
        QTableWidgetItem * item = widget->item(row,0);
        Qt::CheckState status = item->checkState();
        // 判断是否选中，选中状态行的id列单元格值记录到集合中
        if(status == Qt::CheckState::Checked) {
            QTableWidgetItem * item = widget->item(row,idColumn);
            ids.append(item->text().toInt());
        }
    }
    return ids;
}

// ==============查找到表格(主键)id列所在表格的列索引=========================================================
const int TableWidgetOpt::findQTableWidgetIdZnNameColumn(QTableWidget *widget)
{
    // 找出id所在列所在索引值
    int idColumnNum = 0;
    int columnCount = widget->horizontalHeader()->count();
    // 循环表格所有列
    for(int columnNum = 0;columnNum< columnCount;columnNum++) {
        // 获得列表头信息
        QTableWidgetItem * headerItem = widget->horizontalHeaderItem(columnNum);
        QString headerItemText = headerItem->text();
        // 如果表头显示名称等于id的中文名称，则返回该列所在列表的索引值
        if(headerItemText == UserDefineConstant::ID_ZN_NAME) {
            idColumnNum = columnNum;
            break;
        }
    }
    return idColumnNum;
}

// ==============创建表格列表头信息=========================================================
const void TableWidgetOpt::createQTableWidgetHeader(QTableWidget *tableWidget, QList<QString> columnNames)
{
    tableWidget->clear();
    int column = 0;
    tableWidget->setColumnCount(columnNames.size());
    // 循环指定的列名集合，向对应表格插入对应的列信息
    for(QString columnName: columnNames) {
        tableWidget->setHorizontalHeaderItem(column, new QTableWidgetItem(columnName));
        column++;
    }
}

// ==============查询数据库数据并向指定列表插入数据=========================================================
const int TableWidgetOpt::selectDataBaseTableDataToQTableWidget(QTableWidget *tableWidget, QString tableName, QList<QString> columnNames,
                                     int page, int size, QList<QueryConditions> conditions, bool ispaging)
{
    if(ObjectUtil::isNull(tableWidget) || ObjectUtil::isEmpty(tableName) || ObjectUtil::isEmpty(columnNames)) {
        return 0;
    }
    int allCount = DataBaseOpt::selectAllCount(tableName, conditions);
    //------------------------拼接select查询语句开始---------
    // 查询具体参数
    QString sql = "select ";
    if(!columnNames.contains(UserDefineConstant::ID_COLUMN_NUIQUE_NAME)) {
        columnNames.insert(0, UserDefineConstant::ID_COLUMN_NUIQUE_NAME);
    }
    int index = 0;
    for(QString columnName: columnNames) {
        if(index == columnNames.size() -1) {
            sql = sql + columnName;
        } else {
            sql = sql + columnName + ",";
        }
        index++;
    }
    sql = sql + " from " + tableName;
    if(conditions.size() != 0) {
        sql = sql + " where " + DataBaseOpt::getWhere(conditions);
    }
    if(ispaging) {
        sql = sql + " order by " + UserDefineConstant::ID_COLUMN_NUIQUE_NAME + " desc limit "+ QString::number(DataBaseOpt::getStartIndex(page,size)) +","+ QString::number(size);
    } else {
        sql = sql + " order by " + UserDefineConstant::ID_COLUMN_NUIQUE_NAME + " desc";
    }
    qInfo()<<"执行查询语句："<<sql;
    //------------------------拼接select查询语句结束---------
    // 移除表格所有行
    for(int row = tableWidget->rowCount() - 1;row >= 0; row--)
    {
        tableWidget->removeRow(row);
    }
	int row = 0;
    QSqlQuery query = DataBaseManage::getQuery();
    query.exec(sql);
    while(query.next()) { // 循环查询出的数据集
        int index_row = tableWidget->rowCount();
        qInfo()<<"表格行："<< index_row;
        tableWidget->setRowCount(index_row+1);
        QTableWidgetItem *check = new QTableWidgetItem();
        check->setCheckState(Qt::Unchecked);
        check->setFlags(check->flags() ^ Qt::ItemIsEditable);
        tableWidget->setItem(row,0,check); //插入复选框
        int table_column = 0;
        QString info = "";
        for(int column = 1; column <= columnNames.size();column++) {
            QTableWidgetItem* item = new QTableWidgetItem(query.value(table_column).toString());
            if(columnNames.value(column -1) == UserDefineConstant::ID_COLUMN_NUIQUE_NAME) {
                // id列设为不可编辑
                item->setFlags(Qt::NoItemFlags);
            }
            tableWidget->setItem(row,column,item);// 设置列数据
            info = info + QString::number(table_column)+":"+query.value(table_column).toString() + "|";
            table_column++;
        }
        qInfo()<<"更新表格数据"+QString::number(row)<<":"<<info;
        row++;
    }
    return allCount;
}

/**
 * @brief autoAdjustmentTableWidth 自动调整表格列宽
 * @param tableWidget 列表对象
 * @param defaultMinWidthParam 默认最小自动分配的表格宽度，表示的是当显示表格的宽度比这个值小的时候就不会进行自动分配宽度了,而是会以横向滚动条显示
 * @param defaultMinItemWidthParam 自动分配时默认最小时单列的宽度，当自动分配是计算出的平均列宽小于该值，会采用该值进行设置
 * @param columnWidthMap 用户自定义设置列宽，key为表格列索引，从0开始，value表示设置改列的宽度，当设置的有效列数量和表格总列数相同时，自动分配就会失效
 */
const void TableWidgetOpt::autoAdjustmentQTableWidgetWidth(QTableWidget *tableWidget,int defaultMinWidthParam,int defaultMinItemWidthParam,QMap<int,int> columnWidthMap)
{
    // 默认最小的列表宽度，表示的是当显示列表的宽度比这个值小的时候就不会进行自动分配宽度了
    int defaultMinWidth = defaultMinWidthParam;
    // 自动分配时默认最小时单列的宽度，当columnWidthMap设置的总宽度和自动分配计算出的列宽度之和大于了显示列表宽度时，自动分配列会采用的值
    int defaultMinItemWidth = defaultMinItemWidthParam;
    // 获取显示的列头宽度
    int width = tableWidget->horizontalHeader()->width();
    qDebug()<<"width:"<<width;
    // 列头总数
    int tableAllCount = tableWidget->horizontalHeader()->count();
    // 显示的列头总数
    int showTableCount = 0;
    // 显示列头所在列索引的集合
    QList<int> showColumns;
    // 计算实际的所有显示列的宽度之和
    int actualWidth = 0;
    for(int column = 0;column<tableAllCount;column++) {
        // 这里处理掉隐藏的列，隐藏列不参与分配，如果隐藏列参与分配，就会出现显示的出现空白，因为空白部分被隐藏列占据了
        if(!tableWidget->isColumnHidden(column)) {
            actualWidth = actualWidth + tableWidget->columnWidth(column);
            showTableCount++;
            showColumns.append(column);
        }
    }
    //    qDebug()<<"showTableCount:"<<showTableCount;
    // width < defaultMinWidth的作用就是当显示列表的宽度比默认最小的列表宽度小的时候就不会进行自动分配宽度了，也就是在这里会被拦截
    // 当显示列表的宽度比默认最小的列表宽度要大时，就会进行自动调整，同时只要计算出的实际宽度比显示的列头宽度要大，就不用重新调整大小重新进行分配
    if(actualWidth > width && width < defaultMinWidth) {
        return;
    }
    // 计算出设置列的总宽度
    int setItemAllWidth = 0;
    // 有效的设置集合
    QMap<int,int> validColumnWidthMap;
    QList<int> keys = columnWidthMap.keys();
    for(int key: keys) {
        if(key >=0 && key < tableAllCount && showColumns.contains(key)) {
            int value = columnWidthMap.value(key, 0);
            setItemAllWidth = setItemAllWidth + value;
            validColumnWidthMap.insert(key, value);
            //            qDebug()<<"key:"<<key<<"value:"<<value;
        }
    }
    int autoColumnCount = showTableCount-validColumnWidthMap.size();
    int autoAllColumnWidth = setItemAllWidth > width ? 0: width - setItemAllWidth;
    // 计算出每列的平均宽度(这里单独区分出一个第一个自动分配宽度的值是因为除法有误差，所以单独一个就能解决误差问题带来的填充超出或小一点的问题)
    int columnItemWidth = defaultMinItemWidth;
    int fisrtColumnItemWidth = defaultMinItemWidth;
    // 如果需要自动分配的列数量不为0，则计算自动分配列的宽度
    if(autoColumnCount != 0) {
        columnItemWidth = autoAllColumnWidth / autoColumnCount;
        fisrtColumnItemWidth = autoAllColumnWidth - (columnItemWidth*(autoColumnCount-1));
    }
    // 计算出的平均值小于设定的默认自动分配最小值，则直接按最小值处理
    if(columnItemWidth< defaultMinItemWidth || fisrtColumnItemWidth < defaultMinItemWidth) {
        columnItemWidth = defaultMinItemWidth;
        fisrtColumnItemWidth = defaultMinItemWidth;
    }
    // 设置每列可拖拽,并且平均分配宽度
    bool isFisrt = true;
    for(int count = 0;count<showColumns.size();count++) {
        int column = showColumns.at(count);
        tableWidget->horizontalHeader()->setSectionResizeMode(column, QHeaderView::Interactive);
        // 如果设置的map包含该列，则设置为用户设置的值
        if(validColumnWidthMap.contains(column)) {
            tableWidget->setColumnWidth(column,validColumnWidthMap.value(column));
            continue;
        }
        // 如果不是用户设置列，则按照平均分配设置列宽
        if(isFisrt) {
            tableWidget->setColumnWidth(column,fisrtColumnItemWidth);
            isFisrt = false;
        } else {
            tableWidget->setColumnWidth(column,columnItemWidth);
        }
    }
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------



//-----------------------------------------加载弹出框相关-----------------------------------------------------------------------------------------------------------
LoadingDialog* LoadingDialog::createLoading(QWidget *parent)
{
    return createLoading(true, parent);
}

LoadingDialog *LoadingDialog::createLoading(bool isLoadCountDown, QWidget *parent)
{
    LoadingDialog* loading = new LoadingDialog(isLoadCountDown, parent);
    loading->setModal(true); // 设置为模态框
    loading->setAttribute(Qt::WA_DeleteOnClose); // 关闭时销毁对象
    loading->show();
    loading->raise();
    loading->activateWindow();
    return loading;
}

LoadingDialog::LoadingDialog(QWidget *parent) : LoadingDialog(true, parent)
{

}

LoadingDialog::LoadingDialog(bool isLoadCountDown, QWidget *parent) : QDialog(parent)
{
    this->isLoadCountDown = isLoadCountDown;

    // 去掉标题栏,去掉工具栏，窗口置顶
    setWindowFlags(Qt::FramelessWindowHint | Qt::Tool | Qt::WindowStaysOnTopHint);
    setAttribute(Qt::WA_TranslucentBackground, true);
    setWindowOpacity(0.8); //设置窗体透明度
    initUi(); // 初始化样式

    if (this->isLoadCountDown) {
        // 定时操作
        waitTimer = new QTimer(this);
        connect(waitTimer,SIGNAL(timeout()),this,SLOT(timerOpt()));
        waitTimer->setInterval(1000);
        waitTimer->start();
        // 立即执行一次定时方法，因为定时器第一次会在设置的延迟1秒后执行，所以这里需要提前执行一次，把提示文本变成最新的提示信息
        timerOpt();
    }
}

/**
 * @brief LoadingDialog::initUi UI元素初始化
 */
void LoadingDialog::initUi()
{
    this->setFixedSize(250, 250); // 设置该弹出框的宽高都为250
    m_pCenterFrame = new QFrame(this);
    m_pCenterFrame->setGeometry(10, 10 ,230, 230); // 设置坐标和宽高

    //加载Loading动画
    m_pLoadingMovie = new QMovie(":/image/picture/loading.gif"); // QMovie可以设置动图
    m_pLoadingMovie->setScaledSize(QSize(100, 100)); // 设置显示的动图的宽高都为120
    m_pMovieLabel = new QLabel(m_pCenterFrame);
    m_pMovieLabel->setGeometry(65, 10, 100, 100); // 设置坐标和宽高，坐标的x轴是QFrame的宽度230减去显示图片的宽度100后除以2，这样图片就会在QFrame中居中，这个坐标是相对父元素的坐标
    m_pMovieLabel->setScaledContents(true); // 设置自动适应大小（也就是图像会自动随窗口变大变小自适应）
    m_pMovieLabel->setMovie(m_pLoadingMovie); // 将QMovie设置到Qlabel中显示
    m_pLoadingMovie->start();

    //提示文本
    m_pTipsLabel = new QLabel(m_pCenterFrame);
    m_pTipsLabel->setGeometry(5, 130, 220, 35);
    m_pTipsLabel->setAlignment(Qt::AlignCenter | Qt::AlignHCenter); // 文本居中
    m_pTipsLabel->setObjectName("loadingTips"); // 这里设置名字是为了在css文件中进行样式设置
    m_pTipsLabel->setText(QString("加载中,请稍候... "));

    //取消按钮
    m_pCancelBtn = new QPushButton(m_pCenterFrame);
    m_pCancelBtn->setObjectName("loadingCancelBtn"); // 这里设置名字是为了在css文件中进行样式设置
    m_pCancelBtn->setGeometry(25, 180, 180, 35);
    // 如果允许倒计时，则初始时显示等待中，并且不可点击，否则直接可以点击取消按钮
    if (this->isLoadCountDown) {
        m_pCancelBtn->setText("等待中");
        m_pCancelBtn->setEnabled(false); // 设置是否允许点击
    } else {
        m_pCancelBtn->setText("取消等待");
        m_pCancelBtn->setEnabled(true); // 设置是否允许点击
    }
    connect(m_pCancelBtn, &QPushButton::clicked, this, &LoadingDialog::cancelBtnClicked); // 绑定取消按钮点击事件

    //实例阴影shadow
    QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect(this);
    shadow->setOffset(0, 0); // 设置偏移量
    shadow->setColor(QColor(32, 101, 165)); // 设置颜色
    shadow->setBlurRadius(10); // 设置圆角
    this->setGraphicsEffect(shadow); // 将阴影设置给当前弹出框
}

void LoadingDialog::timerOpt()
{
    m_pTipsLabel->setText(QString("加载中,请稍候... %1s \n 等待倒计时%2s").arg(QString::number(timeCount++),QString::number(waitTime-timeCount)));
    // 大于5秒可以取消等待
    if(timeCount > waitTime) {
        m_pTipsLabel->setText(QString("加载中,请稍候... %1s").arg(QString::number(timeCount++)));
        m_pCancelBtn->setEnabled(true);
        m_pCancelBtn->setText("取消等待");
    }
}

/**
 * @brief LoadingDialog::cancelBtnClicked 取消按钮槽函数
 */
void LoadingDialog::cancelBtnClicked()
{
    if(!ObjectUtil::isNull(waitTimer) && waitTimer->isActive()) {
        waitTimer->stop();
    }
    this->close();
}

/**
 * @brief LoadingDialog::paintEvent 界面绘制
 * @param event 绘制事件
 */
void LoadingDialog::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing); //反锯齿
    painter.setBrush(QBrush(Qt::white));
    painter.setPen(Qt::transparent);
    QRect rect = this->rect();
    rect.setLeft(9);
    rect.setTop(9);
    rect.setWidth(rect.width() - 9);
    rect.setHeight(rect.height() - 9);
    painter.drawRoundedRect(rect, 8, 8);
    QWidget::paintEvent(event);
}

LoadingDialog::~LoadingDialog()
{
    delete m_pLoadingMovie;
    delete m_pMovieLabel;
    delete m_pTipsLabel;
    delete m_pCancelBtn;
    delete m_pCenterFrame;
    delete waitTimer;
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------
